


<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Remote Reference Protocol &mdash; PyTorch master documentation</title>
  

  
  
  
  
    <link rel="canonical" href="https://pytorch.org/docs/stable/rpc/rref.html"/>
  

  

  
  
    

  

  <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
  <!-- <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css" type="text/css" />
  <link rel="stylesheet" href="../_static/css/jit.css" type="text/css" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" type="text/css" />
  <link rel="stylesheet" href="../_static/katex-math.css" type="text/css" />
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" /> 

  
  <script src="../_static/js/modernizr.min.js"></script>

  <!-- Preload the theme fonts -->

<link rel="preload" href="../_static/fonts/FreightSans/freight-sans-book.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="../_static/fonts/FreightSans/freight-sans-medium.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="../_static/fonts/IBMPlexMono/IBMPlexMono-Medium.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="../_static/fonts/FreightSans/freight-sans-bold.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="../_static/fonts/FreightSans/freight-sans-medium-italic.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="../_static/fonts/IBMPlexMono/IBMPlexMono-SemiBold.woff2" as="font" type="font/woff2" crossorigin="anonymous">

<!-- Preload the katex fonts -->

<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Math-Italic.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Main-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Main-Bold.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Size1-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Size4-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Size2-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Size3-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/fonts/KaTeX_Caligraphic-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
</head>

<div class="container-fluid header-holder tutorials-header" id="header-holder">
  <div class="container">
    <div class="header-container">
      <a class="header-logo" href="https://pytorch.org/" aria-label="PyTorch"></a>

      <div class="main-menu">
        <ul>
          <li>
            <a href="https://pytorch.org/get-started">Get Started</a>
          </li>

          <li>
            <div class="ecosystem-dropdown">
              <a id="dropdownMenuButton" data-toggle="ecosystem-dropdown">
                Ecosystem
              </a>
              <div class="ecosystem-dropdown-menu">
                <a class="nav-dropdown-item" href="https://pytorch.org/hub"">
                  <span class=dropdown-title>Models (Beta)</span>
                  <p>Discover, publish, and reuse pre-trained models</p>
                </a>
                <a class="nav-dropdown-item" href="https://pytorch.org/ecosystem">
                  <span class=dropdown-title>Tools & Libraries</span>
                  <p>Explore the ecosystem of tools and libraries</p>
                </a>
              </div>
            </div>
          </li>

          <li>
            <a href="https://pytorch.org/mobile">Mobile</a>
          </li>

          <li>
            <a href="https://pytorch.org/blog/">Blog</a>
          </li>

          <li>
            <a href="https://pytorch.org/tutorials">Tutorials</a>
          </li>

          <li class="active">
            <a href="https://pytorch.org/docs/stable/index.html">Docs</a>
          </li>

          <li>
            <div class="resources-dropdown">
              <a id="resourcesDropdownButton" data-toggle="resources-dropdown">
                Resources
              </a>
              <div class="resources-dropdown-menu">
                <a class="nav-dropdown-item" href="https://pytorch.org/resources"">
                  <span class=dropdown-title>Developer Resources</span>
                  <p>Find resources and get questions answered</p>
                </a>
                <a class="nav-dropdown-item" href="https://pytorch.org/features">
                  <span class=dropdown-title>About</span>
                  <p>Learn about PyTorch’s features and capabilities</p>
                </a>
              </div>
            </div>
          </li>

          <li>
            <a href="https://github.com/pytorch/pytorch">Github</a>
          </li>
        </ul>
      </div>

      <a class="main-menu-open-button" href="#" data-behavior="open-mobile-menu"></a>
    </div>

  </div>
</div>


<body class="pytorch-body">

   

    

    <div class="table-of-contents-link-wrapper">
      <span>Table of Contents</span>
      <a href="#" class="toggle-table-of-contents" data-behavior="toggle-table-of-contents"></a>
    </div>

    <nav data-toggle="wy-nav-shift" class="pytorch-left-menu" id="pytorch-left-menu">
      <div class="pytorch-side-scroll">
        <div class="pytorch-menu pytorch-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          <div class="pytorch-left-menu-search">
            

            
              
              
                <div class="version">
                  master (1.5.0 )
                </div>
              
            

            


  


<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search Docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

            
          </div>

          
<div>
  <a style="color:#F05732" href="https://pytorch.org/docs/stable/rpc/rref.html">
    You are viewing unstable developer preview docs.
    Click here to view docs for latest stable release.
  </a>
</div>

            
            
              
            
            
              <p class="caption"><span class="caption-text">Notes</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../notes/amp_examples.html">Automatic Mixed Precision examples</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/autograd.html">Autograd mechanics</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/broadcasting.html">Broadcasting semantics</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/cpu_threading_torchscript_inference.html">CPU threading and TorchScript inference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/cuda.html">CUDA semantics</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/ddp.html">Distributed Data Parallel</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/extending.html">Extending PyTorch</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/faq.html">Frequently Asked Questions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/large_scale_deployments.html">Features for large-scale deployments</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/multiprocessing.html">Multiprocessing best practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/randomness.html">Reproducibility</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/serialization.html">Serialization semantics</a></li>
<li class="toctree-l1"><a class="reference internal" href="../notes/windows.html">Windows FAQ</a></li>
</ul>
<p class="caption"><span class="caption-text">Language Bindings</span></p>
<ul>
<li class="toctree-l1"><a class="reference external" href="https://pytorch.org/cppdocs/">C++ API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../packages.html">Javadoc</a></li>
</ul>
<p class="caption"><span class="caption-text">Python API</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../torch.html">torch</a></li>
<li class="toctree-l1"><a class="reference internal" href="../nn.html">torch.nn</a></li>
<li class="toctree-l1"><a class="reference internal" href="../nn.functional.html">torch.nn.functional</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tensors.html">torch.Tensor</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tensor_attributes.html">Tensor Attributes</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tensor_view.html">Tensor Views</a></li>
<li class="toctree-l1"><a class="reference internal" href="../autograd.html">torch.autograd</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cuda.html">torch.cuda</a></li>
<li class="toctree-l1"><a class="reference internal" href="../amp.html">torch.cuda.amp</a></li>
<li class="toctree-l1"><a class="reference internal" href="../distributed.html">torch.distributed</a></li>
<li class="toctree-l1"><a class="reference internal" href="../distributions.html">torch.distributions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../hub.html">torch.hub</a></li>
<li class="toctree-l1"><a class="reference internal" href="../jit.html">torch.jit</a></li>
<li class="toctree-l1"><a class="reference internal" href="../nn.init.html">torch.nn.init</a></li>
<li class="toctree-l1"><a class="reference internal" href="../onnx.html">torch.onnx</a></li>
<li class="toctree-l1"><a class="reference internal" href="../optim.html">torch.optim</a></li>
<li class="toctree-l1"><a class="reference internal" href="../quantization.html">Quantization</a></li>
<li class="toctree-l1"><a class="reference internal" href="index.html">Distributed RPC Framework</a></li>
<li class="toctree-l1"><a class="reference internal" href="../random.html">torch.random</a></li>
<li class="toctree-l1"><a class="reference internal" href="../sparse.html">torch.sparse</a></li>
<li class="toctree-l1"><a class="reference internal" href="../storage.html">torch.Storage</a></li>
<li class="toctree-l1"><a class="reference internal" href="../bottleneck.html">torch.utils.bottleneck</a></li>
<li class="toctree-l1"><a class="reference internal" href="../checkpoint.html">torch.utils.checkpoint</a></li>
<li class="toctree-l1"><a class="reference internal" href="../cpp_extension.html">torch.utils.cpp_extension</a></li>
<li class="toctree-l1"><a class="reference internal" href="../data.html">torch.utils.data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../dlpack.html">torch.utils.dlpack</a></li>
<li class="toctree-l1"><a class="reference internal" href="../model_zoo.html">torch.utils.model_zoo</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tensorboard.html">torch.utils.tensorboard</a></li>
<li class="toctree-l1"><a class="reference internal" href="../type_info.html">Type Info</a></li>
<li class="toctree-l1"><a class="reference internal" href="../named_tensor.html">Named Tensors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../name_inference.html">Named Tensors operator coverage</a></li>
<li class="toctree-l1"><a class="reference internal" href="../__config__.html">torch.__config__</a></li>
</ul>
<p class="caption"><span class="caption-text">Libraries</span></p>
<ul>
<li class="toctree-l1"><a class="reference external" href="https://pytorch.org/audio">torchaudio</a></li>
<li class="toctree-l1"><a class="reference external" href="https://pytorch.org/text">torchtext</a></li>
<li class="toctree-l1"><a class="reference external" href="https://pytorch.org/elastic/">TorchElastic</a></li>
<li class="toctree-l1"><a class="reference external" href="https://pytorch.org/serve">TorchServe</a></li>
<li class="toctree-l1"><a class="reference external" href="http://pytorch.org/xla/">PyTorch on XLA Devices</a></li>
</ul>
<p class="caption"><span class="caption-text">Community</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../community/contribution_guide.html">PyTorch Contribution Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../community/governance.html">PyTorch Governance</a></li>
<li class="toctree-l1"><a class="reference internal" href="../community/persons_of_interest.html">PyTorch Governance | Persons of Interest</a></li>
</ul>

            
          

        </div>
      </div>
    </nav>

    <div class="pytorch-container">
      <div class="pytorch-page-level-bar" id="pytorch-page-level-bar">
        <div class="pytorch-breadcrumbs-wrapper">
          















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="pytorch-breadcrumbs">
    
      <li>
        <a href="../index.html">
          
            Docs
          
        </a> &gt;
      </li>

        
      <li>Remote Reference Protocol</li>
    
    
      <li class="pytorch-breadcrumbs-aside">
        
            
            <a href="../_sources/rpc/rref.rst.txt" rel="nofollow"><img src="../_static/images/view-page-source-icon.svg"></a>
          
        
      </li>
    
  </ul>

  
</div>
        </div>

        <div class="pytorch-shortcuts-wrapper" id="pytorch-shortcuts-wrapper">
          Shortcuts
        </div>
      </div>

      <section data-toggle="wy-nav-shift" id="pytorch-content-wrap" class="pytorch-content-wrap">
        <div class="pytorch-content-left">

        
          
          <div class="rst-content">
          
            <div role="main" class="main-content" itemscope="itemscope" itemtype="http://schema.org/Article">
             <article itemprop="articleBody" id="pytorch-article" class="pytorch-article">
              
  <div class="section" id="remote-reference-protocol">
<span id="id1"></span><h1>Remote Reference Protocol<a class="headerlink" href="#remote-reference-protocol" title="Permalink to this headline">¶</a></h1>
<p>This note describes the design details of Remote Reference protocol and walks
through message flows in different scenarios. Make sure you’re familiar with the
<a class="reference internal" href="rpc.html#distributed-rpc-framework"><span class="std std-ref">Distributed RPC Framework</span></a> before proceeding.</p>
<div class="section" id="background">
<h2>Background<a class="headerlink" href="#background" title="Permalink to this headline">¶</a></h2>
<p>RRef stands for Remote REFerence. It is a reference of an object which is
located on the local or a remote worker, and transparently handles reference
counting under the hood. Conceptually, it can be considered as a distributed
shared pointer. Applications can create an RRef by calling
<a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a>. Each RRef is owned by the callee worker
of the <a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> call (i.e., owner) and can be used
by multiple users. The owner stores the real data and keeps track of the global
reference count. Every RRef can be uniquely identified by a global <code class="docutils literal notranslate"><span class="pre">RRefId</span></code>,
which is assigned at the time of creation on the caller of the
<a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> call.</p>
<p>On the owner worker, there is only one <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> instance, which contains
the real data, while on user workers, there can be as many <code class="docutils literal notranslate"><span class="pre">UserRRefs</span></code> as
necessary, and <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> does not hold the data. All usage on the owner will
retrieve the unique <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> instance using the globally unique <code class="docutils literal notranslate"><span class="pre">RRefId</span></code>.
A <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> will be created when it is used as an argument or return value in
<a class="reference internal" href="rpc.html#torch.distributed.rpc.rpc_sync" title="torch.distributed.rpc.rpc_sync"><code class="xref py py-meth docutils literal notranslate"><span class="pre">rpc_sync()</span></code></a>,
<a class="reference internal" href="rpc.html#torch.distributed.rpc.rpc_async" title="torch.distributed.rpc.rpc_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">rpc_async()</span></code></a> or
<a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> invocation, and the owner will be notified
according to update the reference count. An <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> and its data will be
deleted when there is no <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instances globally and there are no
reference to the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> on the owner as well.</p>
</div>
<div class="section" id="assumptions">
<h2>Assumptions<a class="headerlink" href="#assumptions" title="Permalink to this headline">¶</a></h2>
<p>RRef protocol is designed with the following assumptions.</p>
<ul class="simple">
<li><p><strong>Transient Network Failures</strong>: The RRef design aims to handle transient
network failures by retrying messages. Node crashes or permanent network
partition is beyond the scope. When those incidents occur, the application
may take down all workers, revert to the previous checkpoint, and resume
training.</p></li>
<li><p><strong>Non-idempotent UDFs</strong>: We assume the user functions (UDF) provided to
<a class="reference internal" href="rpc.html#torch.distributed.rpc.rpc_sync" title="torch.distributed.rpc.rpc_sync"><code class="xref py py-meth docutils literal notranslate"><span class="pre">rpc_sync()</span></code></a>,
<a class="reference internal" href="rpc.html#torch.distributed.rpc.rpc_async" title="torch.distributed.rpc.rpc_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">rpc_async()</span></code></a> or
<a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> are not idempotent and therefore
cannot be retried. However, internal RRef control messages will be made
idempotent and retryable.</p></li>
<li><p><strong>Out of Order Message Delivery</strong>: We do not assume message delivery order
between any pair of nodes, because both sender and receiver are using multiple
threads. There is no guarantee on which message will be processed first.</p></li>
</ul>
</div>
<div class="section" id="rref-lifetime">
<h2>RRef Lifetime<a class="headerlink" href="#rref-lifetime" title="Permalink to this headline">¶</a></h2>
<p>The goal of the protocol is to delete an <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> at an appropriate time.
The right time to delete an <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> is when there are no living
<code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instances and user code is not holding references to the
<code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> either. The tricky part is to determine if there are any living
<code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instances.</p>
<div class="section" id="design-reasoning">
<h3>Design Reasoning<a class="headerlink" href="#design-reasoning" title="Permalink to this headline">¶</a></h3>
<p>A user can get a <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> in three situations:</p>
<ol class="arabic simple">
<li><p>Receiving a <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> from the owner.</p></li>
<li><p>Receiving a <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> from another user.</p></li>
<li><p>Creating a new <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> owned by another worker.</p></li>
</ol>
<p>Case 1 is the simplest where the owner passes its RRef to a user, where the
owner calls <a class="reference internal" href="rpc.html#torch.distributed.rpc.rpc_sync" title="torch.distributed.rpc.rpc_sync"><code class="xref py py-meth docutils literal notranslate"><span class="pre">rpc_sync()</span></code></a>,
<a class="reference internal" href="rpc.html#torch.distributed.rpc.rpc_async" title="torch.distributed.rpc.rpc_async"><code class="xref py py-meth docutils literal notranslate"><span class="pre">rpc_async()</span></code></a>, or
<a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> and uses its RRef as an argument. In this
case a new <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> will be created on the user. As the owner is the caller,
it can easily update its local reference count on the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code>.</p>
<p>The only requirement is that any
<code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> must notify the owner upon destruction. Hence, we need the first
guarantee:</p>
<p><strong>G1. The owner will be notified when any ``UserRRef`` is deleted.</strong></p>
<p>As messages might come delayed or out-of-order, we need one more guarantee to
make sure the delete message is not processed too soon. If A sends a message to
B that involves an RRef, we call the RRef on A the parent RRef and the RRef on B
the child RRef.</p>
<p><strong>G2. Parent RRef will NOT be deleted until the child RRef is confirmed by the
owner.</strong></p>
<p>In cases 2 and 3, it is possible that the owner has only partial or no knowledge
at all about the RRef fork graph. For example, an RRef could be
constructed on a user, and before the owner receives any RPC call, the
creator user might have already shared the RRef with other users, and those
users could further share the RRef. One invariant is that the fork graph of
any RRef is always a tree, because forking an RRef always
creates a new <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instance on the callee (except if the callee is the
owner), and hence every RRef has a single parent.</p>
<p>The owner’s view on any <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> in the tree has three stages:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">1</span><span class="p">)</span> <span class="n">unknown</span> <span class="o">-&gt;</span> <span class="mi">2</span><span class="p">)</span> <span class="n">known</span> <span class="o">-&gt;</span> <span class="mi">3</span><span class="p">)</span> <span class="n">deleted</span><span class="o">.</span>
</pre></div>
</div>
<p>The owner’s view of the entire tree keeps changing. The owner deletes its
<code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> instance when it thinks there are no living <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>
instances, i.e.,
when <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> is deleted, all <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instances could be either indeed
deleted or unknown. The dangerous case is when some forks are unknown and others
are deleted.</p>
<p><strong>G2</strong> trivially guarantees that no parent <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> can be deleted before
the owner knows all of its children <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instances. However, it is
possible that the child <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> may be deleted before the owner knows its
parent <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>.</p>
<p>Consider the following example, where the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> forks to A, then A forks
to Y, and Y forks to Z.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OwnerRRef</span> <span class="o">-&gt;</span> <span class="n">A</span> <span class="o">-&gt;</span> <span class="n">Y</span> <span class="o">-&gt;</span> <span class="n">Z</span>
</pre></div>
</div>
<p>If all of Z’s messages, including the delete message, are processed by the
owner before all messages from Y, the owner will learn Z’s deletion before
knowing Y. Nevertheless, this does not cause any problem. Because, at least
one of Y’s ancestors will be alive (in this case, A) and it will
prevent the owner from deleting the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code>. More specifically, if the
owner does not know Y, A cannot be deleted due to <strong>G2</strong>, and the owner knows A
as the owner is A’s parent.</p>
<p>Things get a little trickier if the RRef is created on a user:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">OwnerRRef</span>
    <span class="o">^</span>
    <span class="o">|</span>
    <span class="n">A</span> <span class="o">-&gt;</span> <span class="n">Y</span> <span class="o">-&gt;</span> <span class="n">Z</span>
</pre></div>
</div>
<p>If Z calls <a class="reference internal" href="rpc.html#torch.distributed.rpc.RRef.to_here" title="torch.distributed.rpc.RRef.to_here"><code class="xref py py-meth docutils literal notranslate"><span class="pre">to_here()</span></code></a> on the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>, the
owner at least knows A when Z is deleted, because otherwise,
<a class="reference internal" href="rpc.html#torch.distributed.rpc.RRef.to_here" title="torch.distributed.rpc.RRef.to_here"><code class="xref py py-meth docutils literal notranslate"><span class="pre">to_here()</span></code></a> wouldn’t finish. If Z does not call
<a class="reference internal" href="rpc.html#torch.distributed.rpc.RRef.to_here" title="torch.distributed.rpc.RRef.to_here"><code class="xref py py-meth docutils literal notranslate"><span class="pre">to_here()</span></code></a>, it is possible that the owner
receives all messages from Z before any message from A and Y. In this case, as
the real data of the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> has not been created yet, there is nothing to
be deleted either. It is the same as Z does not exist at all. Hence, it’s still
OK.</p>
</div>
<div class="section" id="implementation">
<h3>Implementation<a class="headerlink" href="#implementation" title="Permalink to this headline">¶</a></h3>
<p><strong>G1</strong> is implemented by sending out a delete message in <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>
destructor. To provide <strong>G2</strong>, the parent <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> is put into a context
whenever it is forked, indexed by the new <code class="docutils literal notranslate"><span class="pre">ForkId</span></code>. The parent <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> is
only removed from the context when it receives an acknowledgement message (ACK)
from the child, and the child will only send out the ACK when it is confirmed by
the owner.</p>
</div>
</div>
<div class="section" id="protocol-scenarios">
<h2>Protocol Scenarios<a class="headerlink" href="#protocol-scenarios" title="Permalink to this headline">¶</a></h2>
<p>Let’s now discuss how the above designs translate to the protocol in four
scenarios.</p>
<div class="section" id="user-share-rref-with-owner-as-return-value">
<h3>User Share RRef with Owner as Return Value<a class="headerlink" href="#user-share-rref-with-owner-as-return-value" title="Permalink to this headline">¶</a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">torch</span>
<span class="kn">import</span> <span class="nn">torch.distributed.rpc</span> <span class="k">as</span> <span class="nn">rpc</span>

<span class="c1"># on worker A</span>
<span class="n">rref</span> <span class="o">=</span> <span class="n">rpc</span><span class="o">.</span><span class="n">remote</span><span class="p">(</span><span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="n">torch</span><span class="o">.</span><span class="n">add</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">torch</span><span class="o">.</span><span class="n">ones</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="mi">1</span><span class="p">))</span>
<span class="c1"># say the rref has RRefId 100 and ForkId 1</span>
<span class="n">rref</span><span class="o">.</span><span class="n">to_here</span><span class="p">()</span>
</pre></div>
</div>
<p>In this case, the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> is created on the user worker A, then it is
passed to the owner worker B together with the remote message, and then B
creates the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code>. The method <a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a>
returns immediately, meaning that the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> can be forked/used before
the owner knows about it.</p>
<p>On the owner, when receiving the <a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> call, it
will create the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code>, and returns an ACK to acknowledge <code class="docutils literal notranslate"><span class="pre">{100,</span> <span class="pre">1}</span></code>
(<code class="docutils literal notranslate"><span class="pre">RRefId</span></code>, <code class="docutils literal notranslate"><span class="pre">ForkId</span></code>). Only after receiving this ACK, can A delete its
<code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>. This involves both <strong>G1</strong> and <strong>G2</strong>. <strong>G1</strong> is obvious. For
<strong>G2</strong>, the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> is a child of the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>, and the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>
is not deleted until it receives the ACK from the owner.</p>
<a class="reference internal image-reference" href="https://user-images.githubusercontent.com/16999635/69164772-98181300-0abe-11ea-93a7-9ad9f757cd94.png"><img alt="user_to_owner_ret.png" src="https://user-images.githubusercontent.com/16999635/69164772-98181300-0abe-11ea-93a7-9ad9f757cd94.png" style="width: 500px;" /></a>
<p>The diagram above shows the message flow, where solid arrow contains user
function and dashed arrow are builtin messages. Note that the first two messages
from A to B (<a class="reference internal" href="rpc.html#torch.distributed.rpc.remote" title="torch.distributed.rpc.remote"><code class="xref py py-meth docutils literal notranslate"><span class="pre">remote()</span></code></a> and
<a class="reference internal" href="rpc.html#torch.distributed.rpc.RRef.to_here" title="torch.distributed.rpc.RRef.to_here"><code class="xref py py-meth docutils literal notranslate"><span class="pre">to_here()</span></code></a>) may
arrive at B in any order, but the final delete message will only be sent out
when:</p>
<ul class="simple">
<li><p>B acknowledges <code class="docutils literal notranslate"><span class="pre">UserRRef</span> <span class="pre">{100,</span> <span class="pre">1}</span></code> (G2), and</p></li>
<li><p>Python GC agrees to delete the local <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> instance. This occurs when
the RRef is no longer in scope and is eligible for garbage collection.</p></li>
</ul>
</div>
<div class="section" id="user-share-rref-with-owner-as-argument">
<h3>User Share RRef with Owner as Argument<a class="headerlink" href="#user-share-rref-with-owner-as-argument" title="Permalink to this headline">¶</a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">torch</span>
<span class="kn">import</span> <span class="nn">torch.distributed.rpc</span> <span class="k">as</span> <span class="nn">rpc</span>

<span class="c1"># on worker A and worker B</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">rref</span><span class="p">):</span>
  <span class="k">pass</span>

<span class="c1"># on worker A</span>
<span class="n">rref</span> <span class="o">=</span> <span class="n">rpc</span><span class="o">.</span><span class="n">remote</span><span class="p">(</span><span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="n">torch</span><span class="o">.</span><span class="n">add</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">torch</span><span class="o">.</span><span class="n">ones</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="mi">1</span><span class="p">))</span>
<span class="c1"># say the rref has RRefId 100 and ForkId 1</span>
<span class="n">rpc</span><span class="o">.</span><span class="n">rpc_async</span><span class="p">(</span><span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">rref</span><span class="p">,</span> <span class="p">))</span>
</pre></div>
</div>
<p>In this case, after creating the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> on A, A uses it as an argument in
a followup RPC call to B. A will keep <code class="docutils literal notranslate"><span class="pre">UserRRef</span> <span class="pre">{100,</span> <span class="pre">1}</span></code> alive until it
receives the acknowledge from B (<strong>G2</strong>, not the return value of the RPC call).
This is necessary because A should not send out the delete message until all
previous messages are received, otherwise, the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> could be
deleted before usage as we do not guarantee message delivery order. This is done
by creating a child <code class="docutils literal notranslate"><span class="pre">ForkId</span></code> of RRef, holding them in a map until receives the
owner confirms the child <code class="docutils literal notranslate"><span class="pre">ForkId</span></code>. The figure below shows the message flow.</p>
<a class="reference internal image-reference" href="https://user-images.githubusercontent.com/16999635/69164845-b67e0e80-0abe-11ea-93fa-d24674e75a2b.png"><img alt="user_to_owner_arg.png" src="https://user-images.githubusercontent.com/16999635/69164845-b67e0e80-0abe-11ea-93fa-d24674e75a2b.png" style="width: 500px;" /></a>
<p>Note that the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> could be deleted on B before func finishes or even
starts. However this is OK, as at the time B sends out ACK for the child
<code class="docutils literal notranslate"><span class="pre">ForkId</span></code>, it already acquired the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> instance, which would prevent
it been deleted too soon.</p>
</div>
<div class="section" id="owner-share-rref-with-user">
<h3>Owner Share RRef with User<a class="headerlink" href="#owner-share-rref-with-user" title="Permalink to this headline">¶</a></h3>
<p>Owner to user is the simplest case, where the owner can update reference
counting locally, and does not need any additional control message to notify
others. Regarding <strong>G2</strong>, it is same as the parent receives the ACK from the
owner immediately, as the parent is the owner.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">torch</span>
<span class="kn">import</span> <span class="nn">torch.distributed.rpc</span> <span class="k">as</span> <span class="nn">RRef</span><span class="o">,</span> <span class="nn">rpc</span>

<span class="c1"># on worker B and worker C</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">rref</span><span class="p">):</span>
  <span class="k">pass</span>

<span class="c1"># on worker B, creating a local RRef</span>
<span class="n">rref</span> <span class="o">=</span> <span class="n">RRef</span><span class="p">(</span><span class="s2">&quot;data&quot;</span><span class="p">)</span>
<span class="c1"># say the rref has RRefId 100</span>
<span class="n">dist</span><span class="o">.</span><span class="n">rpc_async</span><span class="p">(</span><span class="s1">&#39;C&#39;</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">rref</span><span class="p">,</span> <span class="p">))</span>
</pre></div>
</div>
<a class="reference internal image-reference" href="https://user-images.githubusercontent.com/16999635/69164921-c990de80-0abe-11ea-9250-d32ad00cf4ae.png"><img alt="owner_to_user.png" src="https://user-images.githubusercontent.com/16999635/69164921-c990de80-0abe-11ea-9250-d32ad00cf4ae.png" style="width: 500px;" /></a>
<p>The figure above shows the message flow. Note that when the <code class="docutils literal notranslate"><span class="pre">OwnerRRef</span></code> exits
scope after the rpc_async call, it will not be deleted, because internally
there is a map to hold it alive if there is any known forks, in which case is
<code class="docutils literal notranslate"><span class="pre">UserRRef</span> <span class="pre">{100,</span> <span class="pre">1}</span></code>. (<strong>G2</strong>)</p>
</div>
<div class="section" id="user-share-rref-with-user">
<h3>User Share RRef with User<a class="headerlink" href="#user-share-rref-with-user" title="Permalink to this headline">¶</a></h3>
<p>This is the most complicated case where caller user (parent <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>),
callee user (child <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code>), and the owner all need to get involved.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">torch</span>
<span class="kn">import</span> <span class="nn">torch.distributed.rpc</span> <span class="k">as</span> <span class="nn">rpc</span>

<span class="c1"># on worker A and worker C</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">rref</span><span class="p">):</span>
  <span class="k">pass</span>

<span class="c1"># on worker A</span>
<span class="n">rref</span> <span class="o">=</span> <span class="n">rpc</span><span class="o">.</span><span class="n">remote</span><span class="p">(</span><span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="n">torch</span><span class="o">.</span><span class="n">add</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">torch</span><span class="o">.</span><span class="n">ones</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="mi">1</span><span class="p">))</span>
<span class="c1"># say the rref has RRefId 100 and ForkId 1</span>
<span class="n">rpc</span><span class="o">.</span><span class="n">rpc_async</span><span class="p">(</span><span class="s1">&#39;C&#39;</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">rref</span><span class="p">,</span> <span class="p">))</span>
</pre></div>
</div>
<a class="reference internal image-reference" href="https://user-images.githubusercontent.com/16999635/69164971-d6adcd80-0abe-11ea-971d-6b7af131f0fd.png"><img alt="user_to_user.png" src="https://user-images.githubusercontent.com/16999635/69164971-d6adcd80-0abe-11ea-971d-6b7af131f0fd.png" style="width: 500px;" /></a>
<p>When C receives the child <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> from A, it sends out a fork request to
the owner B. Later, when the B confirms the <code class="docutils literal notranslate"><span class="pre">UserRRef</span></code> on C, C will perform
two actions in parallel: 1) send out the child ACK to A ,and 2) run the user
provided function. During this time, the parent (A) will hold its
<code class="docutils literal notranslate"><span class="pre">UserRRef</span> <span class="pre">{100,</span> <span class="pre">1}</span></code> alive to achieve <strong>G2</strong>.</p>
</div>
</div>
</div>


             </article>
             
            </div>
            <footer>
  

  

    <hr>

  

  <div role="contentinfo">
    <p>
        &copy; Copyright 2019, Torch Contributors.

    </p>
  </div>
    
      <div>
        Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
      </div>
     

</footer>

          </div>
        </div>

        <div class="pytorch-content-right" id="pytorch-content-right">
          <div class="pytorch-right-menu" id="pytorch-right-menu">
            <div class="pytorch-side-scroll" id="pytorch-side-scroll-right">
              <ul>
<li><a class="reference internal" href="#">Remote Reference Protocol</a><ul>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#assumptions">Assumptions</a></li>
<li><a class="reference internal" href="#rref-lifetime">RRef Lifetime</a><ul>
<li><a class="reference internal" href="#design-reasoning">Design Reasoning</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#protocol-scenarios">Protocol Scenarios</a><ul>
<li><a class="reference internal" href="#user-share-rref-with-owner-as-return-value">User Share RRef with Owner as Return Value</a></li>
<li><a class="reference internal" href="#user-share-rref-with-owner-as-argument">User Share RRef with Owner as Argument</a></li>
<li><a class="reference internal" href="#owner-share-rref-with-user">Owner Share RRef with User</a></li>
<li><a class="reference internal" href="#user-share-rref-with-user">User Share RRef with User</a></li>
</ul>
</li>
</ul>
</li>
</ul>

            </div>
          </div>
        </div>
      </section>
    </div>

  


  

     
       <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
         <script src="../_static/jquery.js"></script>
         <script src="../_static/underscore.js"></script>
         <script src="../_static/doctools.js"></script>
         <script src="../_static/language_data.js"></script>
     

  

  <script type="text/javascript" src="../_static/js/vendor/popper.min.js"></script>
  <script type="text/javascript" src="../_static/js/vendor/bootstrap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js"></script>
  <script type="text/javascript" src="../_static/js/theme.js"></script>

  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>
 
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-90545585-1', 'auto');
  ga('send', 'pageview');

</script>

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-117752657-2"></script>

<script>
  window.dataLayer = window.dataLayer || [];

  function gtag(){dataLayer.push(arguments);}

  gtag('js', new Date());
  gtag('config', 'UA-117752657-2');
</script>

<img height="1" width="1" style="border-style:none;" alt="" src="https://www.googleadservices.com/pagead/conversion/795629140/?label=txkmCPmdtosBENSssfsC&amp;guid=ON&amp;script=0"/>


  <!-- Begin Footer -->

  <div class="container-fluid docs-tutorials-resources" id="docs-tutorials-resources">
    <div class="container">
      <div class="row">
        <div class="col-md-4 text-center">
          <h2>Docs</h2>
          <p>Access comprehensive developer documentation for PyTorch</p>
          <a class="with-right-arrow" href="https://pytorch.org/docs/stable/index.html">View Docs</a>
        </div>

        <div class="col-md-4 text-center">
          <h2>Tutorials</h2>
          <p>Get in-depth tutorials for beginners and advanced developers</p>
          <a class="with-right-arrow" href="https://pytorch.org/tutorials">View Tutorials</a>
        </div>

        <div class="col-md-4 text-center">
          <h2>Resources</h2>
          <p>Find development resources and get your questions answered</p>
          <a class="with-right-arrow" href="https://pytorch.org/resources">View Resources</a>
        </div>
      </div>
    </div>
  </div>

  <footer class="site-footer">
    <div class="container footer-container">
      <div class="footer-logo-wrapper">
        <a href="https://pytorch.org/" class="footer-logo"></a>
      </div>

      <div class="footer-links-wrapper">
        <div class="footer-links-col">
          <ul>
            <li class="list-title"><a href="https://pytorch.org/">PyTorch</a></li>
            <li><a href="https://pytorch.org/get-started">Get Started</a></li>
            <li><a href="https://pytorch.org/features">Features</a></li>
            <li><a href="https://pytorch.org/ecosystem">Ecosystem</a></li>
            <li><a href="https://pytorch.org/blog/">Blog</a></li>
            <li><a href="https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md">Contributing</a></li>
          </ul>
        </div>

        <div class="footer-links-col">
          <ul>
            <li class="list-title"><a href="https://pytorch.org/resources">Resources</a></li>
            <li><a href="https://pytorch.org/tutorials">Tutorials</a></li>
            <li><a href="https://pytorch.org/docs/stable/index.html">Docs</a></li>
            <li><a href="https://discuss.pytorch.org" target="_blank">Discuss</a></li>
            <li><a href="https://github.com/pytorch/pytorch/issues" target="_blank">Github Issues</a></li>
            <li><a href="https://pytorch.org/assets/brand-guidelines/PyTorch-Brand-Guidelines.pdf" target="_blank">Brand Guidelines</a></li>
          </ul>
        </div>

        <div class="footer-links-col follow-us-col">
          <ul>
            <li class="list-title">Stay Connected</li>
            <li>
              <div id="mc_embed_signup">
                <form
                  action="https://twitter.us14.list-manage.com/subscribe/post?u=75419c71fe0a935e53dfa4a3f&id=91d0dccd39"
                  method="post"
                  id="mc-embedded-subscribe-form"
                  name="mc-embedded-subscribe-form"
                  class="email-subscribe-form validate"
                  target="_blank"
                  novalidate>
                  <div id="mc_embed_signup_scroll" class="email-subscribe-form-fields-wrapper">
                    <div class="mc-field-group">
                      <label for="mce-EMAIL" style="display:none;">Email Address</label>
                      <input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL" placeholder="Email Address">
                    </div>

                    <div id="mce-responses" class="clear">
                      <div class="response" id="mce-error-response" style="display:none"></div>
                      <div class="response" id="mce-success-response" style="display:none"></div>
                    </div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->

                    <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_75419c71fe0a935e53dfa4a3f_91d0dccd39" tabindex="-1" value=""></div>

                    <div class="clear">
                      <input type="submit" value="" name="subscribe" id="mc-embedded-subscribe" class="button email-subscribe-button">
                    </div>
                  </div>
                </form>
              </div>

            </li>
          </ul>

          <div class="footer-social-icons">
            <a href="https://www.facebook.com/pytorch" target="_blank" class="facebook"></a>
            <a href="https://twitter.com/pytorch" target="_blank" class="twitter"></a>
            <a href="https://www.youtube.com/pytorch" target="_blank" class="youtube"></a>
          </div>
        </div>
      </div>
    </div>
  </footer>

  <div class="cookie-banner-wrapper">
  <div class="container">
    <p class="gdpr-notice">To analyze traffic and optimize your experience, we serve cookies on this site. By clicking or navigating, you agree to allow our usage of cookies. As the current maintainers of this site, Facebook’s Cookies Policy applies. Learn more, including about available controls: <a href="https://www.facebook.com/policies/cookies/">Cookies Policy</a>.</p>
    <img class="close-button" src="../_static/images/pytorch-x.svg">
  </div>
</div>

  <!-- End Footer -->

  <!-- Begin Mobile Menu -->

  <div class="mobile-main-menu">
    <div class="container-fluid">
      <div class="container">
        <div class="mobile-main-menu-header-container">
          <a class="header-logo" href="https://pytorch.org/" aria-label="PyTorch"></a>
          <a class="main-menu-close-button" href="#" data-behavior="close-mobile-menu"></a>
        </div>
      </div>
    </div>

    <div class="mobile-main-menu-links-container">
      <div class="main-menu">
        <ul>
          <li>
            <a href="https://pytorch.org/get-started">Get Started</a>
          </li>

          <li>
            <a href="https://pytorch.org/features">Features</a>
          </li>

          <li>
            <a href="https://pytorch.org/ecosystem">Ecosystem</a>
          </li>

          <li>
            <a href="https://pytorch.org/mobile">Mobile</a>
          </li>

          <li>
            <a href="https://pytorch.org/hub">PyTorch Hub</a>
          </li>

          <li>
            <a href="https://pytorch.org/blog/">Blog</a>
          </li>

          <li>
            <a href="https://pytorch.org/tutorials">Tutorials</a>
          </li>

          <li class="active">
            <a href="https://pytorch.org/docs/stable/index.html">Docs</a>
          </li>

          <li>
            <a href="https://pytorch.org/resources">Resources</a>
          </li>

          <li>
            <a href="https://github.com/pytorch/pytorch">Github</a>
          </li>
        </ul>
      </div>
    </div>
  </div>

  <!-- End Mobile Menu -->

  <script type="text/javascript" src="../_static/js/vendor/anchor.min.js"></script>

  <script type="text/javascript">
    $(document).ready(function() {
      mobileMenu.bind();
      mobileTOC.bind();
      pytorchAnchors.bind();
      sideMenus.bind();
      scrollToAnchor.bind();
      highlightNavigation.bind();
      mainMenuDropdown.bind();
      filterTags.bind();

      // Remove any empty p tags that Sphinx adds
      $("[data-tags='null']").remove();

      // Add class to links that have code blocks, since we cannot create links in code blocks
      $("article.pytorch-article a span.pre").each(function(e) {
        $(this).closest("a").addClass("has-code");
      });
    })
  </script>
</body>
</html>